#include "opencv.h"
#include "Serial.h"

// 外部声明：接收OpenCV数据的缓冲区（长度7，存储一帧完整数据）
extern int opencv[7];

// 外部声明：解析后得到的有效数据（通常为目标坐标、尺寸等信息）
extern int16_t data1;
extern int16_t data2;
extern int16_t data3;
extern int16_t data4;

int i=0;  								 // 循环变量，用于缓冲区清零

/**
 * @brief  OpenCV数据接收函数（基于状态机实现帧解析）
 * @param  data：串口接收到的单个字节数据
 * @note   功能：按照自定义帧格式接收并验证OpenCV发送的数据，确保数据完整性
 */
void Opencv_Receive_Data(int16_t data)
{
    static u8 state = 0;  				 // 静态状态变量，记录当前解析状态
    
    switch(state) {
        case 0:  						 // 状态0：等待帧头（0x66）
            if(data == 0x66) {
                state = 1;               // 帧头验证通过，进入下一状态
                opencv[0] = data;        // 存储帧头到缓冲区第0位
            } else {
                state = 0;               // 帧头验证失败，重置状态机
                for(i=0;i<7;i++)         // 清空接收缓冲区
                    opencv[i] = 0x00;
            }
            break;
            
        case 1:  						 // 状态1：验证数据长度标识（固定为7）
            if(data == 7) {
                state = 2;               // 长度标识验证通过，进入下一状态
                opencv[1] = data;        // 存储长度标识到缓冲区第1位
            } else {
                state = 0;               // 长度标识验证失败，重置状态机
                for(i=0;i<7;i++)         // 清空接收缓冲区
                    opencv[i] = 0x00;
            }
            break;
            
        case 2:  						 // 状态2：接收X坐标低8位
            state = 3;               	 // 接收完成，进入下一状态
            opencv[2] = data;        	 // 存储X坐标低8位
            break;
            
        case 3:  						 // 状态3：接收X坐标高8位
            state = 4;               	 // 接收完成，进入下一状态
            opencv[3] = data;        	 // 存储X坐标高8位
            break;
            
        case 4:  						 // 状态4：接收Y坐标低8位
            state = 5;               	 // 接收完成，进入下一状态
            opencv[4] = data;        	 // 存储Y坐标低8位
            break;
            
        case 5:  						 // 状态5：接收Y坐标高8位
            state = 6;              	 // 接收完成，进入下一状态
            opencv[5] = data;      	     // 存储Y坐标高8位
            break;
            
        case 6:  						 // 状态6：验证帧尾（0x5B）
            if(data == 0x5B) {  		 // 帧尾验证通过（完整帧接收完成）
                state = 0;               // 重置状态机，准备接收下一帧
                opencv[6] = data;        // 存储帧尾到缓冲区第6位
                Opencv_Data();           // 调用数据解析函数，提取有效信息
            } else { 					 // 帧尾验证失败（数据错误或干扰）
                state = 0;               // 重置状态机
                for(i=0;i<7;i++)         // 清空接收缓冲区，丢弃错误数据
                    opencv[i] = 0x00;
            }
            break;
            
        default:  // 异常状态（如未按预期流程接收）
            state = 0;                   // 重置状态机
            for(i=0;i<7;i++)             // 清空缓冲区，丢弃错误数据
                opencv[i] = 0x00;
            break;
    }
}

/**
 * @brief  OpenCV数据解析函数
 * @note   功能：从完整帧缓冲区中提取有效数据，赋值给全局变量供主程序使用
 */
void Opencv_Data(void)
{
    // 从缓冲区提取有效数据
    data1 = (opencv[3] << 8) | opencv[2];  // 组合X坐标（高8位<<8 + 低8位）
    data2 = (opencv[5] << 8) | opencv[4];  // 组合Y坐标（高8位<<8 + 低8位）
    data3 = 0;  // 预留（未使用）
    data4 = 0;  // 预留（未使用）
}
